package stack

import (
	"lesson01/instructions/base"
	"lesson01/rtda"
)

// DUP 指令用于复制操作数栈顶的值，并将复制的值压入栈顶(dup)
type DUP struct {
	base.NoOperandsInstruction
}

func (e *DUP) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot := stack.PopSlot()
	stack.PushSlot(slot)
	stack.PushSlot(slot)
}

// DUP_X1 指令会复制栈顶的一个值，并将复制的值插入到栈顶以下的第二个位置
type DUP_X1 struct {
	base.NoOperandsInstruction
}

func (e *DUP_X1) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	stack.PushSlot(slot1)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// DUP_X2 指令会复制栈顶的一个值，并将复制的值插入到栈顶以下的第三个位置
type DUP_X2 struct {
	base.NoOperandsInstruction
}

func (e *DUP_X2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	stack.PushSlot(slot1)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// DUP2 指令用于复制操作数栈顶的两个值，并将复制的值压入栈顶(dup)
type DUP2 struct {
	base.NoOperandsInstruction
}

func (e *DUP2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// DUP2_X1 指令用于制栈顶的两个值，并将复制的值插入到栈顶以下的第四个位置
type DUP2_X1 struct {
	base.NoOperandsInstruction
}

func (e *DUP2_X1) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// DUP2_X2 指令用于制栈顶的两个值，并将复制的值插入到栈顶以下的第三个位置
type DUP2_X2 struct {
	base.NoOperandsInstruction
}

func (e *DUP2_X2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	slot4 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot4)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}
